﻿using Infrastructure.Attributes.Ioc;
using Infrastructure.Model;
using Infrastructure.Util;
using Microsoft.AspNetCore.Http;
using ShareCode.Dto;
using ShareCode.Entity;
using ShareCode.Util.Extension;
using ShareCode.Util.Helper;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Configuration.Internal;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Dao
{
    public class BaseBaseDao<T> : SimpleClient<T>, IBaseDao<T> where T : BaseBaseEntity, new()
    {

        public BaseBaseDao() : this(DBConfig.aaa ?? "")
        {

        }
        public BaseBaseDao(string connstr) : base(DBConfig.GetDb(connstr))
        {
            Context.Aop.DataExecuting = DataExecuting;
            Context.Aop.OnDiffLogEvent = DiffLog;
        }


        public BaseBaseDao<T>? GetDao()
        {
            return this;
        }

        public virtual void DataExecuting(object oldValue, DataFilterModel entityInfo)
        {
            if (entityInfo.OperationType == DataFilterType.InsertByObject)
            {
                var model = (BaseBaseEntity)entityInfo.EntityValue;
                model.Id = SnowflakeIDcreator.NextId();

                _ = ObjectHelper.GetInsertObject(model);
            }
        }

        public virtual void DiffLog(DiffLogModel diffLogModel)
        {
            //如果写日志的也直接入库，那么入库操作这个事件一定要取消了，否则就死循环了
            //操作前记录  包含： 字段描述 列名 值 表名 表描述
            //var editBeforeData = it.BeforeData;//插入Before为null，之前还没进库
            //                                   //操作后记录   包含： 字段描述 列名 值  表名 表描述
            //var editAfterData = it.AfterData;
            //var sql = it.Sql;
            //var parameter = it.Parameters;
            //var data = it.BusinessData;//这边会显示你传进来的对象
            //var time = it.Time;
            //var diffType = it.DiffType;//enum insert 、update and delete 
        }

        public virtual  Expressionable<T> GetSearchExpression(PagingDto pars)
        {
            var whereExpression = Expressionable.Create<T>();

            if (pars == default)
            {
                return whereExpression;
            }

            whereExpression.AndIF(pars.SearchField.HasInt("IsDelete"), t => t.IsDelete == pars.SearchField.GetInt("IsDelete"))
            .AndIF(pars.SearchField.HasInt("State"), t => t.State == pars.SearchField.GetInt("State"));

            if (pars.IsDesc.HasValue) {
                if (pars.IsDesc.Value)
                {
                    whereExpression.AndIF(pars.LastId > 0, t => t.Id > pars.LastId);
                }
                else {
                    whereExpression.AndIF(pars.LastId > 0, t => t.Id < pars.LastId);
                }
            }
       
            return whereExpression;
        }


        public async virtual Task<bool> UpdateStateAsync(long Id, int state)
        {
            return await UpdateStateAsync([Id], state);
        }
        public async virtual Task<bool> UpdateStateAsync(List<long> Ids, int state)
        {
            return await UpdateAsync(t => t.State == state, t => Ids.Contains(t.Id));
        }

        public async virtual Task<bool> LogicDeleteByIdAsync(long id)
        {
            return await LogicDeleteByIdAsync([id]);

        }
        public async virtual Task<bool> LogicDeleteByIdAsync(List<long> ids)
        {
            return await UpdateAsync(t => t.IsDelete == 1, t => ids.Contains(t.Id));
        }

        public async virtual Task<bool> UnLogicDeleteByIdAsync(long id)
        {
            return await UnLogicDeleteByIdAsync([id]);
        }
        public async virtual Task<bool> UnLogicDeleteByIdAsync(List<long> ids)
        {
            return await UpdateAsync(t => t.IsDelete == 0, t => ids.Contains(t.Id));
        }

        public PageModel TranslatePageModel(PagingDto model)
        {
            return new PageModel { PageIndex = model.CurrentPage, PageSize = model.PageSize, TotalCount = model.TotalRows };
        }

        public async virtual Task<bool> UpdateAsync(Expression<Func<T, bool>> columns, Expression<Func<T, bool>> whereExpression)
        {
            return await UpdateAsync([columns], whereExpression);
        }
        public async virtual Task<T> FirstAsync(Expression<Func<T, bool>> whereExpression, Expression<Func<T, object>>? orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
        {
            return await Context.Queryable<T>().OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(whereExpression).FirstAsync();
        }


        public async virtual Task<bool> UpdateAsync(Expression<Func<T, bool>>[] columns, Expression<Func<T, bool>> whereExpression)
        {
            var temp = Context.Updateable<T>();

            foreach (var a in columns)
            {
                temp = temp.SetColumns(a);
            }

            return await temp.Where(whereExpression).ExecuteCommandAsync() > 0;
        }

        public async virtual Task<List<T>> GetListAsync(Expression<Func<T, bool>> whereExpression, Expression<Func<T, object>>? orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
        {

            return await Context.Queryable<T>().OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(whereExpression).ToListAsync();
        }

        public async virtual Task<PagingWithDataModel<T>> ListPageAsync(PagingDto? pars)
        {
            pars ??= new PagingDto();

            var myreturn = new PagingWithDataModel<T>(pars);//自动提取分页参数

            Expression<Func<T, bool>> whereExpression = GetSearchExpression(pars).ToExpression();

            if (pars.TotalRows < 1)
            {
                var page = this.TranslatePageModel(myreturn);
                var list = await this.GetPageListAsync(whereExpression, page, t => t.Id, SqlSugar.OrderByType.Desc);
                myreturn.List = list;
                myreturn.TotalRows = page.TotalCount;
            }
            else
            {
                var list = await Context.Queryable<T>().OrderBy(t => t.Id).Where(whereExpression).Take(pars.PageSize).ToListAsync();
                myreturn.List = list;
            }


            return myreturn;
        }

        public async virtual Task<List<T>> ListAsync(PagingDto? pars)
        {
            pars ??= new PagingDto();

            Expression<Func<T, bool>> whereExpression = GetSearchExpression(pars).ToExpression();

            return await GetListAsync(whereExpression, t => t.Id, SqlSugar.OrderByType.Desc);

        }

    }

}
